package myJs.myPkg

import org.scalajs.dom.{BodyInit, Headers, HttpMethod, RequestInit, Response, fetch}

import scala.scalajs.js

import scala.scalajs.js.JSConverters._
import org.scalajs.macrotaskexecutor.MacrotaskExecutor.Implicits._

object MyFetch {

  def delete(
      url: String,
      headers: Map[String, String] = Map.empty,
      data: BodyInit = null,
      rsF: Response => js.Promise[js.Any] = rs => rs.json()
  ) = {
    execDelete(url, headers, data, rsF)
  }

  def deleteRnStr(url: String, headers: Map[String, String] = Map.empty, data: BodyInit = null) = {
    myFetch(url = url, headersMap = headers, httpMethod = HttpMethod.DELETE, data = data).flatMap { response =>
      response.text().toFuture
    }
  }

  def execDelete[T](
      url: String,
      headersMap: Map[String, String] = Map.empty,
      data: BodyInit = null,
      rsF: Response => js.Promise[js.Any] = rs => rs.json()
  ) = {
    fetch(
      url,
      init = new RequestInit {
        headers = headers2Headers(headersMap)
        method = HttpMethod.DELETE
        body = data
      }
    ).toFuture.flatMap { response =>
      rsF(response).toFuture
    }
  }

  def post(
      url: String,
      headers: Map[String, String] = Map.empty,
      data: BodyInit = null,
      rsF: Response => js.Promise[js.Any] = rs => rs.json()
  ) = {
    execPost(url, headers, data, rsF)
  }

  def postRnText(url: String, headers: Map[String, String] = Map.empty, data: BodyInit = null) = {
    myFetch(url = url, headersMap = headers, httpMethod = HttpMethod.POST, data = data).flatMap { response =>
      response.text().toFuture
    }
  }

  def myFetch(
      url: String,
      httpMethod: HttpMethod,
      headersMap: Map[String, String] = Map.empty,
      data: BodyInit = null
  ) = {
    fetch(
      url,
      init = new RequestInit {
        headers = headers2Headers(headersMap)
        method = httpMethod
        body = data
      }
    ).toFuture
  }

  def execPost[T](
      url: String,
      headersMap: Map[String, String] = Map.empty,
      data: BodyInit = null,
      rsF: Response => js.Promise[js.Any] = rs => rs.json()
  ) = {
    fetch(
      url,
      init = new RequestInit {
        headers = headers2Headers(headersMap)
        method = HttpMethod.POST
        body = data
      }
    ).toFuture.flatMap { response =>
      rsF(response).toFuture
    }
  }

  def get(url: String, headers: Map[String, String] = Map.empty) = {
    execGet(url, headers)
  }

  def getRnStr(url: String, headers: Map[String, String] = Map.empty) = {
    myFetchGet(url, headers).flatMap { response =>
      response.text().toFuture
    }
  }

  def myFetchGet(url: String, headersMap: Map[String, String] = Map.empty) = {
    fetch(
      url,
      init = new RequestInit {
        headers = headers2Headers(headersMap)
      }
    ).toFuture
  }

  def execGet(url: String, headersMap: Map[String, String] = Map.empty) = {
    fetch(
      url,
      init = new RequestInit {
        headers = headers2Headers(headersMap)
      }
    ).toFuture.flatMap { response =>
      response.json().toFuture
    }
  }

  def headers2Headers(headers: Map[String, String] = Map.empty) = {
    val arrays = headers.toJSArray.map { case (k, v) =>
      js.Array(k, v)
    }
    new Headers(arrays)
  }

}
